package bll

import (
  "context"
  "gitlab.local/backend/proto/dto"
  "manager/client/grpc"
  log "manager/collector/logger"
  "manager/errors"
  "manager/event"
  "manager/model"
  "manager/model/entity"
  "manager/store"
  "manager/store/postgres"
  "manager/utils"
  "time"

  "manager/auth"
)

type shareEbike struct {
  iShareEbike store.IShareEbike
  iEbike      store.IEbike
  iEbikeType  store.IEbikeType
  IUserEbike  store.IUserEbike
}

var ShareEbike = &shareEbike{
  iShareEbike: postgres.ShareEbike,
  iEbike:      postgres.Ebike,
  iEbikeType:  postgres.EbikeType,
  IUserEbike:  postgres.UserEbike,
}

func (a *shareEbike) init() func() {
  return func() {}
}

func (a *shareEbike) onEvent(data *event.Data) {
  if data == nil || (data.Type != event.Event_UnBind_Bike) {
    return
  }

  log.Info("---------------- shareEbike onEvent data:", utils.ToJsonString(data))
  if event.Event_UnBind_Bike == data.Type {
    // 解析参数
    obj := data.Data.(*event.UnBindBike)
    if obj == nil {
      log.Error("shareEbike onEvent err")
      return
    }

    // 参数校验
    if obj.BikeId == 0 || obj.UserId == 0 {
      log.Errorf("shareEbike onEvent params error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
      return
    }

    // 列表
    _, list, _ := postgres.ShareEbike.List(context.Background(), &model.ShareEbikeListRequest{
      Index:       1,
      Size:        100,
      EbikeId:     &obj.BikeId,
      ShareUserId: &obj.UserId,
    })

    if len(list) == 0 {
      return
    }

    for i := 0; i < len(list); i++ {
      // 删除
      a.Delete(context.Background(), &model.ShareEbikeDeleteRequest{
        Id: list[i].Id,
      })
    }
  }
}

// Create 创建
func (a *shareEbike) Create(ctx context.Context, in *model.ShareEbikeCreateRequest) error {
  var (
    err          error
    ebikeEty     *entity.Ebike
    ebikeTypeEty *entity.EbikeType
    shareCount   int
  )
  // 获取用户Id
  in.UserId, _ = auth.ContextUserID(ctx)

  // 判断用户是不是车主
  b := UserEbike.IsManager(in.UserId, in.EbikeId)
  if !b {
    return errors.EbikeNotPermission.Error()
  }

  // 被分享人用户ID
  shareUser, err := grpc.UCmd.UserInfo(ctx, &dto.UserInfoRequest{
    Phone: in.Phone,
  })
  if err != nil {
    return err
  }

  // 分享的车是不是自己的
  if in.UserId == shareUser.Id {
    return errors.EbikeCannotSharedOneself.Error()
  }
  // 判断 车辆和分享的手机号在里面是否存在
  shareCount, _, err = a.iShareEbike.List(ctx, &model.ShareEbikeListRequest{
    EbikeId: &in.EbikeId,
    Phone:   &in.Phone,
  })

  if shareCount > 0 {
    return errors.EbikeAlreadyShared.Error()
  }

  // 调用user
  outInfo, err := grpc.UCmd.UserInfo(ctx, &dto.UserInfoRequest{
    Phone: in.Phone,
  })
  if err != nil {
    log.Error(err)
    return err
  }

  if outInfo.Id == 0 {
    return errors.EbikeShareUserNotFoundErr.Error()
  }

  // 查询车辆信息
  ebikeEty, err = a.iEbike.Find(ctx, in.EbikeId)
  if err != nil {
    log.Error(err)
    return err
  }

  in.Name = ebikeEty.Name
  in.Status = int(model.ShareWait)

  // 查询车型信息
  ebikeTypeEty, err = a.iEbikeType.Find(ebikeEty.TypeID)
  if err != nil {
    log.Error(err)
    return err
  }
  // 构建创建现场数据
  c := buildShareEbike(in)
  c.Photo = ebikeTypeEty.Image
  c.ShareUserId = outInfo.Id // 分享用户ID
  _, err = a.iShareEbike.Create(ctx, c)
  return err
}

// Update 更新
func (a *shareEbike) Update(ctx context.Context, in *model.ShareEbikeUpdateRequest) error {
  var (
    dict = make(map[string]interface{})
  )

  if in.UserId != nil {
    dict["user_id"] = *in.UserId
  }

  if in.EbikeId != nil {
    dict["ebike_id"] = *in.EbikeId
  }

  if in.ShareUserId != nil {
    dict["share_user_id"] = *in.ShareUserId
  }

  if in.Phone != nil {
    dict["phone"] = *in.Phone
  }

  if in.Name != nil {
    dict["name"] = *in.Name
  }

  if in.ShareTime != nil {
    dict["share_time"] = *in.ShareTime
  }

  if in.Status != nil {
    dict["status"] = *in.Status
  }

  dict["updated_at"] = time.Now().Unix()

  return a.iShareEbike.Update(ctx, in.Id, dict)
}

// Delete 删除
func (a *shareEbike) Delete(ctx context.Context, in *model.ShareEbikeDeleteRequest) error {
  var (
    err error

    ety         *entity.ShareEbike
    userBikeEty *entity.UserEbike
  )

  //查询该车辆分享信息
  ety, err = a.iShareEbike.Find(ctx, in.Id)
  if err != nil {
    log.Error(err)
    return err
  }

  // 判断分享状态，如果未接受的直接删除
  if ety.Status != int(model.ShareOk) {
    err = a.iShareEbike.Delete(ctx, in.Id)
    if err != nil {
      log.Error(err)
      return err
    }
    return err
  }

  //用户删除下面车辆
  no := int(model.IsManagerNo)

  userBikeEty, err = a.IUserEbike.FindByParameter(ctx, &model.UserEbikeRequest{
    UserID:    &ety.ShareUserId,
    EbikeID:   &ety.EbikeId,
    IsManager: &no,
  })

  if err != nil {
    log.Error(err)
    return err
  }
  err = a.iShareEbike.ExecTransaction(ctx, func(ctx context.Context) error {
    // 删除车辆绑定表数据
    err = a.IUserEbike.Delete(ctx, userBikeEty.ID)
    if err != nil {
      log.Error(err)
      return err
    }
    // 删除车辆表数据
    err = a.iShareEbike.Delete(ctx, in.Id)
    if err != nil {
      log.Error(err)
      return err
    }
    return nil
  })

  return err
}

// List 列表查询
func (a *shareEbike) List(ctx context.Context, in *model.ShareEbikeListRequest) (*model.ShareEbikeListResponse, error) {
  var (
    err    error
    total  int
    list   []*entity.ShareEbike
    out    = &model.ShareEbikeListResponse{}
    dtoEty *dto.UserListInfoResponse
    query  = &model.ShareEbikeListRequest{}
  )
  // 过滤状态
  in.FilterStatus = []int{int(model.ShareExpire)}

  UserID, _ := auth.ContextUserID(ctx)
  in.Size, in.Index = utils.PageUtil(in.Size, in.Index)
  // 主动分享用户查询
  if in.Type != nil && *in.Type == int(model.ShareTypeUser) {
    query.UserId = &UserID
  }

  // 被分享用户车辆列表查询
  if in.Type != nil && *in.Type == int(model.ShareTypeShareUser) {
    query.ShareUserId = &UserID
  }
  if in.EbikeId != nil {
    query.EbikeId = in.EbikeId
  }
  if total, list, err = a.iShareEbike.List(ctx, query); err != nil {
    return nil, err
  }

  if len(list) == 0 {
    return out, err
  }

  // 过滤过期的分享
  var newList []*entity.ShareEbike
  var expireShareIds []int64
  for j := 0; j < len(list); j++ {
    if list[j].ShareTime > 0 && list[j].AcceptedAt > 0 &&
      list[j].ShareTime+list[j].AcceptedAt < time.Now().Unix() {
      list[j].Status = int(model.ShareExpire)
      expireShareIds = append(expireShareIds, list[j].Id)
      continue
    }

    // 定义数据
    customData := UserEbike.GetBikeCustomData(UserID, list[j].EbikeId)
    list[j].Name = customData.Name
    list[j].Photo = customData.Image

    newList = append(newList, list[j])
  }

  list = newList

  ids := make([]int64, len(list))
  // 用户查寻分享给谁的车辆
  if *in.Type == int(model.ShareTypeUser) {
    for i, e := range list {
      ids[i] = e.ShareUserId
    }
  }
  // 分享用户查询谁分享给他的
  if *in.Type == int(model.ShareTypeShareUser) {
    for i, e := range list {
      ids[i] = e.UserId
    }
  }

  out.Total = total
  out.List = model.ShareEbikesEntityToDto(list)

  // 查询用户信息
  dtoEty, err = grpc.UCmd.UserListInfo(ctx, &dto.UserListInfoRequest{Ids: ids})
  if err != nil {
    log.Errorf("shareEbike err:%v", err)
  }

  if dtoEty != nil {
    for _, dtor1 := range dtoEty.List {
      for i2, l1 := range out.List {
        if *in.Type == int(model.ShareTypeUser) {
          if l1.ShareUserId == dtor1.Id {
            out.List[i2].UserName = dtor1.Name
          }
        }
        if *in.Type == int(model.ShareTypeShareUser) {
          if l1.UserId == dtor1.Id {
            out.List[i2].UserName = dtor1.Name
          }
        }
      }
    }
  }

  // 更新分享状态
  if len(expireShareIds) > 0 {
    postgres.GetDB(ctx).Model(&entity.ShareEbike{}).Where("id in (?)", expireShareIds).Update("status", int(model.ShareExpire))
  }

  return out, nil
}

// GetEffectiveShareEbike 查询有效的被分享的车辆
func (a *shareEbike) GetEffectiveShareEbike(ctx context.Context, userId int64, bikeIds []int64) (effectIds, expireIds map[int64]struct{}, err error) {

  effectIds = make(map[int64]struct{})
  expireIds = make(map[int64]struct{})

  // 查询有效的分享车辆
  _, list, _ := a.iShareEbike.List(ctx, &model.ShareEbikeListRequest{
    ShareUserId: &userId,
    BikeIds:     bikeIds,
  })

  for i := 0; i < len(list); i++ {
    if list[i].ShareTime > 0 && list[i].AcceptedAt > 0 && list[i].ShareTime+list[i].AcceptedAt < time.Now().Unix() {
      expireIds[list[i].EbikeId] = struct{}{}
      continue
    }

    effectIds[list[i].EbikeId] = struct{}{}
  }

  return
}

// ShareList 列表查询
func (a *shareEbike) ShareList(ctx context.Context, in *model.ShareAllRequest) (*model.ShareEbikeListAllResponse, error) {
  var (
    err error

    list     []*entity.ShareEbike
    infoList []*model.ShareEbikeInfo
    out      = &model.ShareEbikeListAllResponse{}
    dtoEty   *dto.UserListInfoResponse
    query    = &model.ShareEbikeListRequest{}
  )

  UserID, _ := auth.ContextUserID(ctx)
  in.Size, in.Index = utils.PageUtil(in.Size, in.Index)
  query.UserId = &UserID

  // 查询分享车辆信息
  all, err := a.iShareEbike.ShareAll(ctx, UserID)
  for i := 0; i < len(all); i++ {
    customData := UserEbike.GetBikeCustomData(UserID, all[i].ID)
    all[i].Name = customData.Name
    all[i].Photo = customData.Image
  }

  if err != nil {
    log.Error(err)
    return nil, err
  }
  if len(all) == 0 {
    return out, err
  }
  //设置总数
  out.Total = len(all)

  // 查询分享用户信息
  if _, list, err = a.iShareEbike.List(ctx, query); err != nil {
    return nil, err
  }

  if len(list) == 0 {
    return nil, err
  }

  ids := make([]int64, len(list))
  // 用户查寻分享给谁的车辆
  for i, e := range list {
    ids[i] = e.ShareUserId
  }

  // 查询用户信息
  dtoEty, err = grpc.UCmd.UserListInfo(ctx, &dto.UserListInfoRequest{Ids: ids})
  if err != nil {
    log.Error("-----Share List query-------", err)
    return nil, err
  }

  infoList = model.ShareEbikesEntityToDto(list)

  for _, dtor1 := range dtoEty.List {
    for j, l1 := range infoList {
      if l1.ShareUserId == dtor1.Id {
        infoList[j].UserName = dtor1.Name
      }
    }
  }

  for i, allInfo := range all {
    for _, l := range infoList {
      if allInfo.ID == l.EbikeId {
        if l.ShareTime > 0 && l.AcceptedAt > 0 && l.ShareTime+l.AcceptedAt < time.Now().Unix() {
          continue
        }

        all[i].ShareUserList = append(all[i].ShareUserList, l)
        allInfo.Count += 1
      }
    }
  }

  out.List = all
  return out, nil
}

// Accept 接受分享
func (a *shareEbike) Accept(ctx context.Context, in *model.ShareEbikeBaseRequest) error {
  var (
    err           error
    shareEbikeEty *entity.ShareEbike
    updateMap     = make(map[string]interface{}, 0)
  )
  // 查询分享信息
  shareEbikeEty, err = a.iShareEbike.Find(ctx, in.Id)
  if err != nil {
    log.Error(err)
    return err
  }

  // 执行事务
  err = a.iShareEbike.ExecTransaction(ctx, func(ctx context.Context) error {
    //创建车辆绑定信息
    _, err = a.IUserEbike.Create(ctx, &entity.UserEbike{
      UserID:    shareEbikeEty.ShareUserId,
      EbikeID:   shareEbikeEty.EbikeId,
      ShareTime: shareEbikeEty.ShareTime,
      IsManager: int(model.IsManagerNo),
      Photo:     shareEbikeEty.Photo,
      CreatedAt: time.Now().Unix(),
      UpdatedAt: time.Now().Unix(),
    })
    if err != nil {
      log.Error(err)
      return err
    }
    //修改分享车辆状态
    updateMap["status"] = int(model.ShareOk)
    updateMap["updated_at"] = time.Now().Unix()
    updateMap["accepted_at"] = time.Now().Unix()
    err = a.iShareEbike.Update(ctx, in.Id, updateMap)
    if err != nil {
      log.Error(err)
      return err
    }

    // 发送车辆绑定车主事件
    event.Emit(&event.Data{
      Type: event.Event_Bind_Bike,
      Data: &event.BindBike{
        BikeId: shareEbikeEty.EbikeId,
        UserId: shareEbikeEty.ShareUserId,
      },
    })
    return nil
  })
  return err
}

// buildShareEbike 构建创建数据现场
func buildShareEbike(in *model.ShareEbikeCreateRequest) *entity.ShareEbike {
  // todo: check the entity is required
  return &entity.ShareEbike{

    UserId: in.UserId,

    EbikeId: in.EbikeId,

    ShareUserId: in.ShareUserId,

    Phone: in.Phone,

    Name: in.Name,

    ShareTime: in.ShareTime,

    Status: in.Status,

    CreatedAt: time.Now().Unix(),

    UpdatedAt: time.Now().Unix(),
  }
}
